﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace VS2010Test
{
    class MinorChanges
    {

        #region Constructor
        private static MinorChanges _Instance = null;
        private MinorChanges()
        {
        }
        static readonly private object padLock = new object();
        public static MinorChanges Instance
        {
            get
            {
                if (_Instance == null)
                    lock (padLock)
                    {
                        if (_Instance == null)
                            _Instance = new MinorChanges();
                    }
                return _Instance;
            }
        }
        #endregion

        public class Parameters
        {

            #region Constructor
            private static Parameters _Instance = null;
            private Parameters()
            {
            }
            static readonly private object padLock = new object();
            public static Parameters Instance
            {
                get
                {
                    if (_Instance == null)
                        lock (padLock)
                        {
                            if (_Instance == null)
                                _Instance = new Parameters();
                        }
                    return _Instance;
                }
            }
            #endregion
            
            #region Restricctions
            //this doesn't work because default must be a constant
            //void OpParams2(object p = new object())
            //{
            //    Console.WriteLine("x={0} y={1} z={2}", x, y, z);
            //}

            //Parameter arrays can’t be optional
            //ref/out parameters can’t be optional
            #endregion

            //optional parameters come after required ones
            private void OpParams1(int x, int y = 20, int z = 30)
            {
                Console.WriteLine("x={0} y={1} z={2}", x, y, z);
            }

            //optional parameters come after required ones
            //params must be the last one
            //default of the type returns default value for the type (initial values must be constant)
            private void OpParams2(int x, int y = default(Int32), int z = 30, params string[] other)
            {
                Console.WriteLine("x={0} y={1} z={2}", x, y, z);
            }           

            public void OptionalParametersTest()
            {
                OpParams1(1, 2, 3);
                //the next 3 calls are the same
                OpParams1(1, 2);
                OpParams1(x: 1, y: 2);
                OpParams1(y: 2, x: 1);

                OpParams1(1);
                //using default value for y
                OpParams1(1, z: 40);

                OpParams2(1, 2, 3, new string[] { "a" });
                OpParams2(1, 2, 3);
            }

            private void AppendTimestamp(string filename, string message, Encoding encoding = null, DateTime? timestamp = null)
            {
                Encoding realEncoding = encoding ?? Encoding.UTF8;
                DateTime realTimestamp = timestamp ?? DateTime.Now;
                using (TextWriter writer = new StreamWriter(filename, true, realEncoding))
                {
                    writer.WriteLine("{0:s}: {1}", realTimestamp, message);
                }
            }

            public void NullForNoConstantDefaultValues()
            {
                AppendTimestamp("test.txt", "msg");
                AppendTimestamp("test.txt", "msg", Encoding.ASCII);
                AppendTimestamp("test.txt", "msg", timestamp: DateTime.Now.AddDays(2));
            }
        }
    }
}
